//
// Created by whg on 2025-06-01.
//

#ifndef PYVM_2025_BUFFERED_INPUT_STREAM_HPP
#define PYVM_2025_BUFFERED_INPUT_STREAM_HPP

#include <stdio.h>
#include <stdexcept>
#include <cstring>

#define BUFFER_LEN 256

using namespace std;

class BufferedInputStream{
private:
    FILE* fp;
    char buffer[BUFFER_LEN];
    unsigned short index;

public:
    BufferedInputStream(const char* fileName){
        fp = fopen(fileName, "rb");
        if(!fp){
            throw runtime_error(string(fileName) + " : " + strerror(errno));
        }
        init();
    }

    ~BufferedInputStream(){
        close();
    }

    char read(){
        if(index >= BUFFER_LEN){
            init();
        }
        return buffer[index++];
    }

    int readInt(){
        int b1 = read() & 0xff;
        int b2 = read() & 0xff;
        int b3 = read() & 0xff;
        int b4 = read() & 0xff;
        return b4 << 24 | b3 << 16 | b2 << 8 | b1;
    }

    void unread(){
        index--;
    }

    void init(){
        fread(buffer, BUFFER_LEN * sizeof(char), 1, fp);
        index = 0;
    }

    void close(){
        if(fp != nullptr){
            fclose(fp);
            fp = nullptr;
        }
    }
};

#endif //PYVM_2025_BUFFERED_INPUT_STREAM_HPP
